/*-
 * Copyright (c) 2012, Columbia University
 * All rights reserved.
 *
 * This software was developed by Georgios Kontaxis <kontaxis@cs.columbia.edu>
 * at Columbia University, New York, NY, USA, in January 2012.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Columbia University nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>

#include "config.h"
#include "debug.h"

#define BUF_SIZE 100 /* MAX size for input line */


void free_config () {
  int i;

  struct agent *agent;
  struct agent *tmp;

  for (i = 0; i <= MAX_GROUP_N; i++) {

    agent = agents[i];

    if ((agent = agents[i]))
      while(agent) {
        tmp = agent;
        agent = agent->next;
        free (tmp);
      }
  }
}


void parse (char *filename) {

  int i;

  /* intermediate variables, holding values 
   * that will end up in a (struct agent) 
   * structure. */
  char *group;
  unsigned int group_n;
  char *host;
  char *port;

  /* auxilirary vars 
   * - count of entries read
   * - config file line count */
  unsigned int agent_count = 0;
  unsigned int config_count = 0;
  unsigned int line = 0;
  
  struct agent *agent;
  struct agent *new_agent;

  /* input buffer */
  char buf [BUF_SIZE + 1];

  FILE *fp = fopen (filename, "r");
  if (!fp) {
    fprintf (stderr, 
             "%s:%s:%d error: failed to open '%s' for reading.\n", 
             __FILE__, __func__, __LINE__, filename); 
    return;
  }

  while (1) {

    /* clear contents of input buffer */
    bzero (buf, BUF_SIZE + 1);

    /* break on no data read */
    if (!fgets (buf, BUF_SIZE, fp)) break;

    line++;

    /* skip comment lines */
    if (buf[0] == '#') continue;

    debug_print("> read: '%s'\n", buf);

    /* parse line, extract tokens */
    group = strtok (buf, " ");
     host = strtok (NULL, " ");
     port = strtok (NULL, " ");
    if (!group || !host || !port) {
      fprintf (stderr, 
               "%s:%s:%d error: unable to extract group/host/port " 
               "from line %u\n", 
               __FILE__, __func__, __LINE__, line);
      continue;
    }

    group_n = (unsigned int) atoi(group);

    if (group_n > MAX_GROUP_N) {
      fprintf (stderr, 
               "%s:%s:%d error: invalid group number %u in line %u\n", 
               __FILE__, __func__, __LINE__, line, group_n);
      continue;
    }

    agent = agents[group_n];

    while (agent && agent->next) {agent = agent->next;}

    /* allocate memory for new agent structure */
    new_agent = malloc (sizeof(struct agent));
    if (!new_agent) {
      perror ("malloc");
      continue;
    } 

    /* append new agent to the end of its group */
    if (!agent) {agents[group_n] = new_agent;}
    else agent->next = new_agent;

    /* populate new agent structure */
    new_agent->group = (unsigned int) atoi(group);
    new_agent->host = gethostbyname (host);
    new_agent->port = (unsigned int) atoi(port);

    agent_count++;
  }

  fclose (fp);

  /* print stats and all read entries (debug) */

  for (i = 0; i <= MAX_GROUP_N; i++)
    if (agents[i]) config_count++;

  info_print("read %u agent entries in " 
             "%u distinct configurations\n", 
             agent_count, config_count);

  for (i = 0; i <= MAX_GROUP_N; i++) {

    agent = agents[i];
    while (agent) {
      info_print("* [%u] %s %u [%s]\n", 
                 agent->group, agent->host->h_name, agent->port, 
                 (agent == agents[i])?"PRIMARY":"SECONDARY");
      agent = agent->next;
    }
  }
}


#if FALSE
int main (int argc, char *argv[]) {

  if (argc > 1) 
    parse (argv[1]);

  return 0;
}
#endif
